home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / devices / null.1 next >
Text File  |  1988-12-06  |  14KB  |  450 lines

  1. Path: xanth!ames!ncar!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i091:  null - dos handler like nil:
  5. Message-ID: <10495@swan.ulowell.edu>
  6. Date: 5 Dec 88 23:00:05 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 439
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: gno@stacken.kth.se (Gunnar Nordmark)
  12. Posting-number: Volume 2, Issue 91
  13. Archive-name: devices/null.1
  14.  
  15. This is a dos-handler called null: that acts like NIL: except this is
  16. is a *real* handler.
  17.  
  18. [uuencoded binary also included here; it's small.  ..Bob]
  19.  
  20. #    This is a shell archive.
  21. #    Remove everything above and including the cut line.
  22. #    Then run the rest of the file through sh.
  23. #----cut here-----cut here-----cut here-----cut here----#
  24. #!/bin/sh
  25. # shar:    Shell Archiver
  26. #    Run the following text with /bin/sh to create:
  27. #    Makefile
  28. #    MountList
  29. #    amigaline-D1
  30. #    misc.c
  31. #    null.c
  32. #    null.doc
  33. #    null.uu
  34. # This archive created: Mon Dec  5 17:54:58 1988
  35. cat << \SHAR_EOF > Makefile
  36. #########################################################################
  37. #
  38. #        null-handler Makefile
  39. #        V 0.0 (c) Gunnar Nordmark 1988
  40. #        For Manx 3.6a
  41. #
  42. #########################################################################
  43.  
  44.  
  45. null-handler    : misc.o null.o
  46.     ln  -o null-handler misc.o null.o -lc32
  47.  
  48. misc.o    : misc.c 
  49.     cc +L +Hnull.syms misc.c
  50.  
  51. null.o    : null.c
  52.     cc +L +Inull.syms null.c
  53. SHAR_EOF
  54. cat << \SHAR_EOF > MountList
  55.  
  56. /*  
  57.     Installs null-handler V 0.0 (C) Gunnar Nordmark
  58. */
  59.  
  60. null:      Handler = L:null-handler
  61.            Stacksize = 500
  62.            Priority = 5
  63.        GlobVec = 1
  64. #
  65. SHAR_EOF
  66. cat << \SHAR_EOF > amigaline-D1
  67.     AMIGALINE #D1,    Matthew Dillon
  68.  
  69.     Disconnecting a program such that you can EndCLI and also allow the
  70.     program to call Execute().
  71.  
  72. Problem:
  73.  
  74.     You want to disconnect a program such that when you RUN <nil: >nil:
  75.     (using the new 1.3 RUN) you can then EndCLI the cli.
  76.  
  77.     This program wants to be able to use Execute() to run other programs. 
  78.     The problem is that Execute() requires a valid pr_ConsoleTask (console)
  79.     or it will freeze.
  80.  
  81. Solution: General
  82.  
  83.     Run <nil: >nil: mycprogram
  84.  
  85.     If using the main() entry point, you can fclose(stderr) to remove
  86.     the reference to "*".  If using the _main() entry point, stdio is
  87.     not setup and thus you do not need to do this (in fact, you can't
  88.     use stdio at all without crashing the computer).
  89.  
  90.     note: being able to fclose(stderr) from the main() entry point 
  91.     works with Aztec C.  I don't know about Lattice.  Aztec always
  92.     does an Open("*", 1006) to setup stderr and this reference must
  93.     be removed.
  94.  
  95.                     --
  96.  
  97.     At this point, you can EndCLI and the cli window goes away.  However,
  98.     the 'mycprogram' cannot call Execute() or otherwise run other 
  99.     external programs for two reasons:
  100.  
  101.         (1) pr_ConsoleTask is still non-NULL and points to the now
  102.             defunct window (i.e. you will cause a task-held requester)
  103.  
  104.         (2) you cannot set pr_ConsoleTask to NULL... Execute() does
  105.             not accept it and freezes up.
  106.  
  107.                     --
  108.  
  109.     So, you must set pr_ConsoleTask to some other valid device.  Guess
  110.     what?  Any device will do except NIL: which isn't a real device.  For
  111.     example, RAM: :
  112.  
  113.         extern APTR DeviceProc();
  114.         proc->pr_ConsoleTask = DeviceProc("ram:");
  115.  
  116.         (assuming RAM: exists)
  117.  
  118.     What does this do?  Any program which tries to open the console will
  119.     actually open the file "RAM:*", as in Open("RAM:*", 1006).  
  120.     Unfortunetly, there is no way to place "*" in anything but the 
  121.     root directory of the device.  This is essentially a garbage file.
  122.  
  123.     But the ultimate goal is achieved ... you can kill the CLI window
  124.     and still arbitrarily run programs from the detached program with
  125.     impunity.
  126.  
  127.     The only possible problem which I have yet to test is when several
  128.     programs try to access RAM:* as their console at the same time.  
  129.     Since the file is openned 1006, other programs trying to Open() it
  130.     will fail while the first programs is still running.  What happens?
  131.  
  132.                             -Matt
  133. SHAR_EOF
  134. cat << \SHAR_EOF > misc.c
  135. /*
  136.  *  misc.c  - support routines - Phillip Lindsay (C) Commodore 1986
  137.  *  You may freely distribute this source and use it for Amiga Development -
  138.  *  as long as the Copyright notice is left intact.
  139.  *
  140.  * 30-SEP-86
  141.  *
  142.  */
  143. #include <functions.h>
  144. #include <stdio.h>
  145. #include <exec/types.h>
  146. #include <exec/nodes.h>
  147. #include <exec/lists.h>
  148. #include <exec/ports.h>
  149. #include <exec/libraries.h>
  150. #include <exec/devices.h>
  151. #include <exec/io.h>
  152. #include <exec/memory.h>
  153. #include <devices/console.h>
  154. #include <libraries/dos.h>
  155. #include <libraries/dosextens.h>
  156. #include <libraries/filehandler.h>
  157.  
  158. extern void returnpkt();
  159.  
  160. /* returnpkt() - packet support routine
  161.  * here is the guy who sends the packet back to the sender...
  162.  *
  163.  * (I modeled this just like the BCPL routine [so its a little redundant] )
  164.  */
  165.  
  166. void
  167. returnpktplain(packet, myproc)
  168. struct DosPacket *packet;
  169. struct Process *myproc;
  170. {
  171.     returnpkt(packet, myproc, packet->dp_Res1, packet->dp_Res2);
  172. }
  173.  
  174. void
  175. returnpkt(packet, myproc, res1, res2)
  176. struct DosPacket *packet;
  177. struct Process *myproc;
  178. ULONG  res1, res2;
  179. {
  180.     struct Message *mess;
  181.     struct MsgPort *replyport;
  182.  
  183.     packet->dp_Res1          = res1;
  184.     packet->dp_Res2          = res2;
  185.     replyport                = packet->dp_Port;
  186.     mess                     = packet->dp_Link;
  187.     packet->dp_Port          = &myproc->pr_MsgPort;
  188.     mess->mn_Node.ln_Name    = (char *) packet;
  189.     mess->mn_Node.ln_Succ    = NULL;
  190.     mess->mn_Node.ln_Pred    = NULL;
  191.     PutMsg(replyport, mess);
  192. }
  193.  
  194.  
  195. /*
  196.  * taskwait() ... Waits for a message to arrive at your port and
  197.  *   extracts the packet address which is returned to you.
  198.  */
  199.  
  200. struct DosPacket *
  201. taskwait(myproc)
  202. struct Process *myproc;
  203. {
  204.     struct MsgPort *myport;
  205.     struct Message *mymess;
  206.  
  207.     myport = &myproc->pr_MsgPort;
  208.     WaitPort(myport);
  209.     mymess = GetMsg(myport);
  210.     return((struct DosPacket *)mymess->mn_Node.ln_Name);
  211. }
  212.  
  213. /* end of misc.c    */
  214.  
  215.  
  216. SHAR_EOF
  217. cat << \SHAR_EOF > null.c
  218. /****************************************************************************
  219.  *
  220.  *  null driver V0.0 (c)CopyRight 1988, Gunnar Nordmark.  All Rights Reserved.
  221.  *  
  222.  *  null-handler Ver. 0.0  20-Jul-1988
  223.  *
  224.  *  Gunnar Nordmark
  225.  *  Nora strand 5
  226.  *  182 34 DANDERYD
  227.  *  SWEDEN
  228.  *
  229.  *  |You may freely distribute this source as long as |
  230.  *  |the Copyright notice is left intact.          |
  231.  ***************************************************************************/
  232.  
  233. #undef  BADDR
  234. #define BADDR(x)   ((APTR)((long)x << 2))
  235.  
  236. #define ACTION_FINDINPUT    1005L
  237. #define ACTION_FINDOUTPUT    1006L
  238. #define ACTION_END         1007L
  239.  
  240. #define DOS_FALSE            0L
  241. #define DOS_TRUE                -1L
  242.  
  243. /* My Globals */
  244.  
  245. long            SysBase;
  246. struct Process      *myproc;
  247.  
  248. _main()
  249. {
  250.     extern void returnpkt();        /* sends back the packet          */
  251.     extern void returnpktplain();    /* use args in Res1               */
  252.     extern struct DosPacket *taskwait();
  253.  
  254.            char       *version =     "Ver 0.0 (c) Gunnar Nordmark 1988";
  255.     struct DosPacket  *mypkt;          /* a pointer to the dos packet    */
  256.     struct DeviceNode *mynode;         /* our device node (parmpkt Arg3) */
  257.     struct FileHandle *fh;         /* a pointer to our file handle      */
  258.     long          run = TRUE;    /* handler main loop flag      */
  259.     int              null_open = 0;    /* null open count          */
  260.  
  261.  
  262.     /* Initializing the handler */
  263.  
  264.     myproc      = (struct Process *)FindTask(0L);
  265.     mypkt       = taskwait(myproc);      /* Wait for my startup message */
  266.  
  267.     /* I don't need the name or extra info passed in Arg1/2 */
  268.  
  269.     mynode          = (struct DeviceNode *)BADDR(mypkt->dp_Arg3);
  270.     mynode->dn_Task     = &myproc->pr_MsgPort; 
  271.     returnpkt(mypkt, myproc, DOS_TRUE, mypkt->dp_Res2); 
  272.  
  273.     /* done initial stuff, now for some work */
  274.  
  275.     while(run) {
  276.     mypkt = taskwait(myproc);
  277.  
  278.     switch(mypkt->dp_Type) {    /* find what action to perform */
  279.  
  280.     case ACTION_FINDINPUT:
  281.     case ACTION_FINDOUTPUT:
  282.  
  283.         null_open++;
  284.  
  285.         fh = (struct FileHandle  *)BADDR(mypkt->dp_Arg1);
  286.         fh->fh_Arg1 = mypkt->dp_Type;
  287.         fh->fh_Port = (struct MsgPort *)DOS_FALSE; /* not interactive */
  288.  
  289.         returnpkt(mypkt, myproc, DOS_TRUE, mypkt->dp_Res2);
  290.         break;
  291.  
  292.     case ACTION_READ:
  293.  
  294.         returnpkt(mypkt, myproc, 0, mypkt->dp_Res2); /* zero-length=EOF */
  295.         break;
  296.  
  297.     case ACTION_WRITE:
  298.         
  299.         mypkt->dp_Res1 = mypkt->dp_Arg3;  /* tell em we wrote them all */
  300.         returnpktplain(mypkt, myproc);
  301.         break;
  302.  
  303.     case ACTION_END:
  304.  
  305.         if (--null_open == 0)
  306.         run = 0;
  307.  
  308.         returnpkt(mypkt, myproc, DOS_TRUE, mypkt->dp_Res2);
  309.         break;
  310.  
  311.     default:
  312.  
  313.         returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
  314.         break;
  315.     }
  316.     } /* end while */
  317.     mynode->dn_Task = FALSE; 
  318. }
  319. SHAR_EOF
  320. cat << \SHAR_EOF > null.doc
  321. ***************************************************************************
  322. *
  323. *    null.doc    20 Nov 88    Gunnar Nordmark
  324. *
  325. ***************************************************************************
  326.  
  327. What is null:?
  328.  
  329. Tt's a new animal that you will be glad to put in your private ZOO,
  330. (also known as the L: directory).
  331.  
  332. "Oh no, not another silly handler!" you cry, but read on!
  333.  
  334. In the very good article by Matt Dillon, AMIGALINE#D1, that I've included
  335. in this distribution, the problem is fully explained.
  336. I suggests that you take a look at the file amigaline-D1 before reading
  337. further.
  338.  
  339. As Matt explains, the NIL: device is not a "real" device. In fact it is no
  340. device at all in the physical sense. It is just an Amiga-DOS convention
  341. that says: If you have a process-identifier for a device, and that identifier
  342. is just a null pointer, then that "identifier" referrs to the NIL: device.
  343.  
  344. Did you get that? I'm not surprised if you didn't, because it *is* strange.
  345.  
  346. I'll try to explain:
  347. Every normal dos-device is a process that have an own private message-port
  348. that is used as a comunication link between AmigaDOS and the device.
  349. Since you must know the address of the message port of a device in order
  350. to comunicate with it, it is a natural decision that that address also is
  351. used as the identifier of the device.
  352.  
  353. AmigaDOS has a function called DeviceProc() that finds the address for you.
  354. If you say  port=DeviceProc("RAM:")  you get the address of the message prot
  355. of the RAM: device.
  356.  
  357. Now the strange part:
  358. If you try  port=DeviceProc("NIL:")  and then sends packets to that port
  359. you'll crash the machine instantly.
  360. Why? 
  361. Because NIL: has *no* message-port at all.
  362. When you have a NULL-pointer as identifier for a handler, the identifier
  363. referrs to the NIL: device.
  364.  
  365. The *only* reason I can think of for this lack of generality, is efficiency.
  366. You save time, becase you don't have to comunicate with a device.
  367. You save memory, because you don't have to start a new process named NIL:.
  368.  
  369. But unfortunately this has a lot of drawbacks. Most of them are deadly.
  370. The reason is that AmigaDOS does *not* allways check for the NIL: oddity.
  371. Sometimes it thinks that the NULL-pointer (the NIL: identifier) is a
  372. valid message port and merilly sends messages to it. Poof!
  373.  
  374. The solution is a new dos-device called "null:".
  375. This is a real dos-device that has has its own message port. It just doesn't
  376. do anything useful. It behaves exactly as NIL: i.e. you can write to it,
  377. and read from it (then you get EOF).
  378.  
  379. The great thing about null: is that you can say
  380.  
  381.         extern APTR DeviceProc();
  382.         proc->pr_ConsoleTask = DeviceProc("null:");
  383.  
  384. and you'll be able to close the console. (see amigaline-D1)
  385.  
  386. Any process can open null: as many times as it like.
  387. And it doesn't matter if you say
  388.         Open("null:" MODE_OLDFILE);
  389.         Open("null:*" MODE_NEWFILE);
  390.         Open("null:@#$@!!" MODE_OLDFILE);
  391.         Open("null:foo.bar" MODE_OLDFILE);
  392. everything works.
  393.  
  394. To install null: just append the included mountlist to DEVS:MountList
  395. Copy null-handler to your L: directory and say  Mount null:
  396.  
  397. I have used it for half a year now with no problems at all. I have a
  398. written my own version of AmiCron that uses null: as pr_ConsoleTask.
  399. That means I now have a cron-deamon that doesn't requires a window
  400. to run!
  401.  
  402. I wan't to thank Steve Drew who wrote the aux-handler that was posted
  403. to the net last year. I've "stolen" all the code from that handler. :-)
  404. I hope you don't mind Steve.
  405.  
  406.   - Gunnar
  407.  
  408.   Gunnar Nordmark
  409.   Nora strand 5
  410.   S-182 34 DANDERYD
  411.   SWEDEN
  412.  
  413.   gno@stacken.kth.se
  414.   stacken.kth.se!gno@uunet.uu.net  (if the above doesn't work)
  415.   gno@SESTAK.BITNET
  416. SHAR_EOF
  417. cat << \SHAR_EOF > null.uu
  418.  
  419. begin 644 null-handler
  420. M```#\P`````````#``````````(```#*````%@````$```/I````RD[Z`FY.8
  421. M50``(&T`""\H`!`@;0`(+R@`#"\M``PO+0`(80A/[P`03EU.=4Y5__@@;0`(I
  422. M(6T`$``,(&T`""%M`!0`$"!M``@K:``$__@@;0`(*U#__"!M``@B;0`,T_P`>
  423. M``!<(4D`!"!M__PA;0`(``H@;?_\0I`@;?_\0J@`!"\M__PO+?_X3KH"@E!/7
  424. M3EU.=4Y5__@@;0`(T?P```!<*TC__"\M__Q.N@)P6$\O+?_\3KH"2%A/*T#_F
  425. M^"!M__@@*``*3EU.=4Y5_^A!^@&"*TC__"M\`````?_L0JW_Z$*G3KH""%A/]
  426. M*4"`$B\L@!).NO^@6$\K0/_X(&W_^"`H`!SE@"M`__0@;?_T(FR`$M/\````R
  427. M7"%)``@@;?_X+R@`$$AX__\O+(`2+RW_^$ZZ_OQ/[P`02JW_[&<``0@O+(`2&
  428. M3KK_3EA/*T#_^"!M__@@*``(8```QE*M_^@@;?_X("@`%.6`*T#_\"!M__@B#
  429. M;?_P(V@`"``D(&W_\$*H``0@;?_X+R@`$$AX__\O+(`2+RW_^$ZZ_I9/[P`00
  430. M8```HB!M__@O*``00J<O+(`2+RW_^$ZZ_GA/[P`08```A"!M__@B;?_X(V@`;
  431. M'``,+RR`$B\M__A.NOXP4$]@9%.M_^AF!$*M_^P@;?_X+R@`$$AX__\O+(`2"
  432. M+RW_^$ZZ_C!/[P`08#Q(>`#10J<O+(`2+RW_^$ZZ_AA/[P`08"20O````%)GB
  433. M`/]\6X!GE)"\```#EF<`_R93@&<`_R!3@&>>8,1@`/[T(&W_]$*H``A.74YU)
  434. M5F5R(#`N,"`H8RD@1W5N;F%R($YO<F1M87)K(#$Y.#@``&%P0^R`#D7L@`ZU4
  435. MR68.,CP`$FL(=``BPE')__PI3X`6+'@`!"E.@`Y(YX"`""X`!`$I9Q!+^@`(O
  436. M3J[_XF`&0J?S7TYS0_H`($ZN_F@I0(`:9@PN/``#@`=.KO^48`1.NOWV4$]."
  437. M=61O<RYL:6)R87)Y`$GY``!__DYU3OH``B)O``0L;(`.3N[^VD[Z``(@;P`$6
  438. M+&R`#D[N_HQ,[P,```0L;(`.3N[^DD[Z``(@;P`$+&R`#D[N_H````/L````,
  439. M`0````$```+D`````````_(```/J`````P`4`````````````````_(```/K$
  440. (`````0```_+D:
  441. ``
  442. end
  443. size 908
  444. SHAR_EOF
  445. #    End of shell archive
  446. exit 0
  447. -- 
  448. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  449. Have five nice days.
  450.